<?php
	if (!class_exists('MyDebuger'))
		die('Se requiere de la clase \'MyDebuger\' para utilizar la clase \'Brain\'');
		
	final class Brain extends MyDebuger {
		/* nombre del cerebro */
		private $nombre		= Null;
		/* bandera para verificar si se creo el objeto */
		private $isCreate		= False;
		/* DemoTime */
		private $demoTimeOk	= True;
		
		/** Objetos integrantes de esta clase **/
		/* array contenedor de las clases necesarias */
		private $clasesNecesarias	= Array(
			'bytes'		=> 'Bytes',
			'corrector'	=>	'Corrector',
			'conexion'	=>	'MySqlAssistant',
			'cpu'			=>	'CPUStats',
			'mem'			=> 'MEMStats',
			'num2letra'	=>	'NumToLetras',
			'smtp'		=>	'SMTPMailer'
		);
		
		/* Corrector de palabras */
		private $corrector			= False;
			/* ruta al diccionario */
			private $dicFile				= 'espanol.dic';
			
		/* Link a la DB */
		private $conexion				= False;
			/* datos para la conexion */
			private $userConexion		= 'test';
			private $passConexion		= 'test';
			private $hostConexion		= 'localhost';
			private $dbConexion			= 'calendario';
			
		/* estado del procesador */
		private $cpu					= False;
		
		/* estado de la memoria */
		private $mem					= False;
		
		/* convertidor de numeros a letras */
		private $num2letra			= False;
			/* depuracion completa para el convertidor de numeros */
			private $num2letrasDebug	= False;
			
		/* convertidor de Bytes */
		private $bytes					= False;
		
		/* SMTP sender */
		private $smtp					= False;
			/* SMTP Server */
			private $smtpHostName		= 'email.supernet.com.py';
			/* SMTP Port */
			private $smtpHostPort		= 25;
		
		/** DEFAULT METHOD FORMAT **/
		private function _defaultMethodFormat_() {
			try {
				try {
					/* verificamos si el objeto esta creado */
					$this->verificarObjeto();
					/** CODE HERE **/
				} catch (ErrorException $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$this->convertToMyException($e);
				}
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$this->show($e->getMensaje($this->html));
			}
		}
		
		/* constructor */
		public function __construct($nombre = 'MyBrain') {
			try {
				try {
					/* creamos el padre 'MyDebuger' */
					parent::__construct($nombre);
					/* habilitamos la salida pura de errores */
					$this->habilitarErrores();
					/* guardamos el nombre */
					$this->nombre = $nombre;
					/* creamos los obtejos integrantes */
					$this->crearObjetos();
					/* obtenemos el estado del sistema al finalizar la creacion del objeto */
					$this->estadoSistema();
					/* si todo fue bien cambiamos la bandera de creacion */
					$this->isCreate = True;
				} catch (ErrorException $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$this->convertToMyException($e);
				}
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$this->show($e->getMensaje($this->html));
			}
		}
		
		public function __destruct() {
			/* verificamos si se creo el objeto */
			if ($this->isCreate) {
				/* mostramos un mensaje */
				$this->show('Finalizando procesos', False); $this->show('..');
				/* matamos todos los objetos */
				$this->killObjects();
				/* mostramos un mensaje */
				$this->show('Finalizando ejecucion..', False);
				/* mostramos OK al mensaje */
				$this->showOK();
			}
			/* matamos el padre */
			parent::__destruct();
		}
		
		private function killObjects() {
			/* recorremos el array con los objetos */
			foreach ($this->clasesNecesarias AS $objeto => $clase)
				/* matamos el objeto */
				unset($this->$objeto);//->__destruct();
		}
		
		private function habilitarErrores() {
			/* habilitamos la depuracion HTML */
			$this->enableHtmlDebug();
			/* mostramos un mensaje */
			$this->show('Habilitando salida de errores..', False);
			/* verificamos la bandera de DemoTime */
			if ($this->demoTimeOk)
				/* habilitamos el DemoTime rapido */
				$this->enableDemoTime(True);
			/* mostramos OK al mensaje */
			$this->showOK();
		}
		
		/* creador de objetos */
		private function crearObjetos() {
			/* verificamos si existen las clases necesarias */
			$this->verificarExistenciaClases();
			/* creamos los objetos que necesitamos */
			$this->creacionObjetos();
			/* cargamos los valores de los objetos */
			$this->cargarValores();
			/* mostramos un mensaje de exito */
			$this->show('Creacion de objetos integrantes finalizada', False); $this->show('');
		}
		
		private function cargarValores() {
			/* mostramos un mensaje */
			$this->show('Cargando valores a objetos integrantes..', False); $this->show('');
			/* obtenemos el estado de la memoria al iniciar */
			$this->ActualMemUsage();
			/* cargamos los valores para la conexion MySQL */
			$this->loadConexion();
			/* cargamos los valores del Corrector */
			$this->loadCorrector();
			/* cargamos los valores de Convertidor a letras */
			$this->loadConvertidorLetras();
			/* cargamos los valores para el SMTP */
			$this->loadSmtpLink();
		}
		
		private function loadConexion() {
			$this->show('Cargando valores para la conexion MySQL..', False); $this->show('');
			/* asignamos el usuario */
			$this->conexion->setUser($this->userConexion);
			/* asignamos la contrasena */
			$this->conexion->setPass($this->passConexion);
			/* asignamos la DB */
			$this->conexion->setDB($this->dbConexion);
			/* conectamos */
			$this->show('Probando conexion MySQL..', False); $this->show('');
			$this->conexion->conectar();
			/* ejecutamos unas consultas */
			$this->conexion->iniciarTransaccion();
			$this->conexion->selectFrom('eventos');
			$filas = $this->conexion->getNumRows();
			$this->show('Cantidad de filas: ' . $filas, False); $this->show('');
			$this->conexion->cancelarTransaccion();
		}
		
		private function loadCorrector() {
			/* cargamos el diccionario */
			$this->show('Cargando valores para el corrector..', False); $this->show('');
			$this->corrector->cargarDiccionario($this->dicFile);
			/* probamos el corrector */
			$this->show('Probando corrector..', False); $this->show('');
			$this->corrector->probar(10, 15, False);
		}
		
		private function loadConvertidorLetras() {
			/* habilitamos la depuracion completa */
			$this->num2letra->enableFullDebug($this->num2letrasDebug);
			/* cargamos la matriz de valores */
			$this->show('Cargando valores para el convertidor..', False); $this->show('');
			$this->num2letra->loadMatrix();
			/* probamos el corrector */
			$this->show('Probando convertidor..', False); $this->show('');
			$this->num2letra->convertir((rand(0,1) ? '-' : '') . rand(1000, 50000) . '.' . rand(0,999));
		}
		
		private function loadSmtpLink() {
			/* mostramos un mensaje */
			$this->show('Cargando valores para el smtp..', False); $this->show('');
			/* asignamos el host server */
			$this->smtp->setHostName($this->smtpHostName);
			/* asignamos el puerto de conexion */
			$this->smtp->setHostPort($this->smtpHostPort);
			/* asignamos unos datos de prueba */
			$this->smtp->setEmail('hschimpf@gschimpf.com');
			$this->smtp->addDestino(Array('algo.algo@algo.com', 'false@algo.com'), 'CC');
			$this->smtp->addBodyLine('Linea de prueba..');
			$this->smtp->enviarEmail();
		}
		
		private function verificarExistenciaClases() {
			/* mostramos un mensaje */
			$this->show('Verificando existencia de clases integrantes..', False);
			/* recorremos el atributo 'clasesNecesarias' que es un Array con las clases que utilizamos */
			foreach ($this->clasesNecesarias AS $clase) {
				/* verificamos si existe */
				if (!class_exists($clase))
					/* salimos con una excepcion */
					$this->newException("Se requiere de la clase '$clase' para utilizar la clase 'Brain'");
			}
			/* OK a las clases */
			$this->showOK();
			/* mostramos un mensaje */
			$this->show('Verificando existencia de atributos para objetos integrantes..', False);
			/* recorremos el atributo 'clasesNecesarias' que es un Array con las clases que utilizamos */
			foreach ($this->clasesNecesarias AS $atributo => $clase) {
				/* verificamos si existe el atrubuto */
				if (!isset($this->$atributo))
					/* salimos con una excepcion */
					$this->newException("Se requiere del atributo '$atributo' para utilizar la clase 'Brain'");
			}
			/* OK a las clases */
			$this->showOK();
		}
		
		private function creacionObjetos() {
			/* mostramos un mensaje */
			$this->show('Creando objetos integrantes..', False); $this->show('');
			/* recorremos el Array de clases necesarias */
			foreach ($this->clasesNecesarias AS $nombreObjeto => $claseObjeto) {
				/* mostramos un mensaje del objeto que estamos creando */
				$this->show('Creando objeto \'' . $this->newName($nombreObjeto) . '\'..', False);
				/* creamos el objeto */
				$this->$nombreObjeto = new $claseObjeto($this->newName($nombreObjeto));
				/* mostramos OK al mensaje */
				$this->showOK();
				/* habilitamos la depuracion en el objeto */
				$this->habilitarDepuracionObjeto($nombreObjeto, $claseObjeto);
			}
		}
		
		private function habilitarDepuracionObjeto($nombreObjeto, $nombreClase) {
			$this->show('Habilitando depuracion en el objeto \'' . $this->newName($nombreObjeto) . '\'..', False);
			/* obtenemos los metodos de la clase */
			$clase = get_class_methods($nombreClase);
			/* verificamos si la clase posee los metodos necesarios */
			if (in_array('enableHtmlDebug', $clase) && in_array('enableDemoTime', $clase)) {
				/* habilitamos la depuracion en el objeto */
				$this->$nombreObjeto->enableHtmlDebug();
				/* verificamos la bandera de DemoTime */
				if ($this->demoTimeOk)
					/* habilitamos el DemoTime del objeto */
					$this->$nombreObjeto->enableDemoTime(True);
				/* mostramos OK al mensaje */
				$this->showOK();
			} else
				/* si la clase no posee los metodos mostramos un mensaje */
				$this->show('El objeto no posee metodos de depuracion');
		}
		
		private function estadoSistema() {
			/* obtenemos el estado del procesador al finalizar la creacion */
			$this->CpuUsageOnCreation();
			/* obtenemos el estado de la memoria al finalizar */
			$this->ActualMemUsage();
		}
		
		private function CpuUsageOnCreation() {
			/* mostramos un mensaje */
			$this->show('Obteniendo estado del CPU al finalizar la creacion', False); $this->show('..');
			/* obtenemos el estado del procesador */
			$estado = $this->cpu->getData('cpu');
			/* mostramos el estado del CPU */
			$this->show('Estado del CPU: ' . number_format($estado, 2, ',', '.') . ' %', False); $this->show('');
		}
		
		private function ActualMemUsage() {
			/* mostramos un mensaje */
			$this->show('Obteniendo uso actual de la memoria', False); $this->show('..');
			/* obtenemos el estado de la memoria */
			$uso = $this->mem->getData();
			/* mostramos el estado del CPU */
			$this->show('Uso actual de la memoria: ' . $this->bytes->convertir($uso['used']), False); $this->show('');
		}
		
		private function getMyName() {
			/* retornamos el nombre */
			return $this->nombre;
		}
		
		private function newName($val) {
			/* retornamos el nombre del objeto y le agregamos la cadena deseada */
			return $this->getMyName() . '::' . ucfirst(strtolower($val));
		}
		
		private function verificarObjeto() {
			/* verificamos si el objeto esta creado */
			if (!$this->isCreate)
				/* enviamos una excepcion para matar el proceso */
				$this->newException('El objeto no esta creado');
		}
	}
?>
